home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / c / etc / RCS / fmt.c,v < prev    next >
Text File  |  1992-09-18  |  39KB  |  1,449 lines

  1. head     1.9;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.9
  10. date     92.09.18.09.56.55;  author mgbaker;  state Exp;
  11. branches ;
  12. next     1.8;
  13.  
  14. 1.8
  15. date     90.09.11.14.17.10;  author kupfer;  state Exp;
  16. branches ;
  17. next     1.7;
  18.  
  19. 1.7
  20. date     90.07.25.16.51.51;  author douglis;  state Exp;
  21. branches ;
  22. next     1.6;
  23.  
  24. 1.6
  25. date     90.01.30.23.11.59;  author jhh;  state Exp;
  26. branches ;
  27. next     1.5;
  28.  
  29. 1.5
  30. date     90.01.30.11.27.03;  author jhh;  state Exp;
  31. branches ;
  32. next     1.4;
  33.  
  34. 1.4
  35. date     90.01.26.11.53.41;  author douglis;  state Exp;
  36. branches ;
  37. next     1.3;
  38.  
  39. 1.3
  40. date     89.10.24.12.26.13;  author jhh;  state Exp;
  41. branches ;
  42. next     1.2;
  43.  
  44. 1.2
  45. date     89.06.19.14.16.11;  author jhh;  state Exp;
  46. branches ;
  47. next     1.1;
  48.  
  49. 1.1
  50. date     89.06.05.12.34.44;  author jhh;  state Exp;
  51. branches ;
  52. next     ;
  53.  
  54.  
  55. desc
  56. @@
  57.  
  58.  
  59. 1.9
  60. log
  61. @Finished bug due to lack of initialization that caused Fmt_Size
  62. to screw up buffer alignment in the kernel and thus report the wrong
  63. size.
  64. @
  65. text
  66. @/* 
  67.  * fmt.c --
  68.  *
  69.  *    Routines for converting between different formats of data.
  70.  *    A data format includes such things as byte-order and 
  71.  *    alignment. 
  72.  *
  73.  * Copyright 1989 Regents of the University of California
  74.  * Permission to use, copy, modify, and distribute this
  75.  * software and its documentation for any purpose and without
  76.  * fee is hereby granted, provided that the above copyright
  77.  * notice appear in all copies.  The University of California
  78.  * makes no representations about the suitability of this
  79.  * software for any purpose.  It is provided "as is" without
  80.  * express or implied warranty.
  81.  */
  82.  
  83. #ifndef lint
  84. static char rcsid[] = "$Header: /sprite/src/lib/c/etc/RCS/fmt.c,v 1.8 90/09/11 14:17:10 kupfer Exp Locker: mgbaker $ SPRITE (Berkeley)";
  85. #endif /* not lint */
  86. /*LINTLIBRARY*/
  87.  
  88.  
  89. #include <sprite.h>
  90. #include <stdlib.h>
  91. #include <ctype.h>
  92. #include <string.h>
  93. #include <sys.h>
  94. #include "fmt.h"
  95.  
  96. /*
  97.  * Two supported byte-orders.
  98.  */
  99. #define BIG_ENDIAN 0
  100. #define LITTLE_ENDIAN 1
  101.  
  102. /*
  103.  * Structure for each format. Right now formats only include alignment
  104.  * and byte-order. The alignment fields for bytes, halfwords, words,
  105.  * and doublewords are used to align these data types such that their
  106.  * addresses are a multiple of the alignment.  For example, an alignment
  107.  * of 4 indicates that the address of the data must be a multiple of
  108.  * 4. The alignments for structures and unions are used in the same
  109.  * way, except that they represent the minimum alignment. If the
  110.  * structure or union contains a more restrictive data type the more
  111.  * restrictive alignment is used.
  112.  * 
  113.  * There are two supported byte-orders: little-endian and big-endian.
  114.  * If we view a word as an array of 4 bytes, then byte 0 is the most
  115.  * significant byte of the word if a machine is big-endian and the
  116.  * least significant if the machine is little endian.
  117.  */
  118.  
  119. typedef struct {
  120.     int        bAlign;            /* Byte alignment */
  121.     int        hAlign;            /* Halfword alignment */
  122.     int        wAlign;            /* Word alignment */
  123.     int        dAlign;            /* Doubleword alignment */
  124.     int        structMinAlign;        /* Minimum alignment of structures */
  125.     int        unionMinAlign;        /* Minimum alignment of unions */
  126.     int        byteOrder;        /* Byte order. */
  127. } FormatInfo;
  128.  
  129. /*
  130.  * Byte-order and alignment information for each type.
  131.  */
  132. static FormatInfo formatInfo[] = {
  133.     {1,    2, 2, 2, 2, 2, BIG_ENDIAN},           /* 68K */
  134.     {1, 2, 4, 4, 1, 1, LITTLE_ENDIAN},        /* VAX */
  135.     {1, 2, 4, 8, 4, 4, LITTLE_ENDIAN},       /* SPUR */
  136.     {1, 2, 4, 8, 1, 1, LITTLE_ENDIAN},       /* MIPS */
  137.     {1, 2, 4, 8, 1, 1, BIG_ENDIAN},        /* SPARC */
  138.     {1, 2, 2, 2, 1, 1, LITTLE_ENDIAN}        /* Symmetry */
  139. };
  140.  
  141. /*
  142.  * Number of different formats.
  143.  */
  144. static int formatCount = sizeof(formatInfo) / sizeof(FormatInfo);
  145.  
  146. /*
  147.  * Structure to maintain state of current conversion.
  148.  */
  149. typedef struct {
  150.     char        *contPtr;    /* Ptr to position in content string */
  151.     char        *inEndPtr;    /* Ptr to last byte in input buffer */
  152.     char        *inPtr;        /* Ptr to position in input buffer */
  153.     char        *inStartPtr;    /* Starting input pointer. */
  154.     char        *outEndPtr;    /* Ptr to last byte in output buffer */
  155.     char        *outPtr;    /* Ptr to position in output buffer */
  156.     char        *outStartPtr;    /* Starting output pointer. */
  157.     FormatInfo        *inInfoPtr;    /* Ptr to format info for in format */
  158.     FormatInfo        *outInfoPtr;    /* Ptr to format info for out format */
  159. } State;
  160.  
  161. /*
  162.  * Used to convert Swap_Buffer constants to Fmt constants.
  163.  */
  164.  
  165. static int compat[3] = { 1, 4, 3};
  166.  
  167. /*
  168.  * Forward declaration of procedures.
  169.  */
  170. static int    ConvertSequence _ARGS_((Boolean doCopy, int unionIndex,
  171.                     int openChar, State *statePtr));
  172. static int    ConvertStruct _ARGS_((Boolean doCopy, Boolean doingUnion,
  173.                       State *statePtr, int *repCountPtr));
  174. static int    ConvertUnion _ARGS_((Boolean doCopy, Boolean doingUnion,
  175.                      State *statePtr, int *repCountPtr));
  176. static int    ConvertByte _ARGS_((Boolean doCopy, int repCount,
  177.                     State *statePtr));
  178. static int    ConvertHalfWord _ARGS_((Boolean doCopy, int repCount,
  179.                     State *statePtr));
  180. static int    ConvertWord _ARGS_((Boolean doCopy, int repCount,
  181.                     State *statePtr));
  182. static int    ConvertDoubleWord _ARGS_((Boolean doCopy, int repCount,
  183.                       State *statePtr));
  184. static int    CalcComplexAlign _ARGS_((State *statePtr, char **contPtrPtr,
  185.                      int *repCountPtr, int *inAlignPtr,
  186.                      int *outAlignPtr));
  187.  
  188. /*
  189.  * AlignPointer --
  190.  *
  191.  * Macro to increment a pointer to the given alignment. 
  192.  * The offset is the address of the start of the buffer, since it may
  193.  * not be aligned.  To align a pointer we add in the alignment minus one,
  194.  * then subtract the original alignment (low bits of the offset). 
  195.  * The address is then rounded to the alignment by anding with the inverse
  196.  * of the alignment minus one.  The original alignment is then added back in.
  197.  */
  198.  
  199. #define AlignPointer(align, offset, ptr) { \
  200.     (ptr) = (char *) (( \
  201.     (((int)(ptr)) + (align) - 1 - (((int) offset) & ((align)-1))) \
  202.     & ~((align)-1)) \
  203.     + (((int)offset) & ((align)-1))); \
  204. }
  205.  
  206. /*
  207.  * Return the maximum of two numbers.
  208.  */
  209. #define MAX(a,b) ((a) > (b)) ? (a) : (b)
  210.  
  211. /*
  212.  *----------------------------------------------------------------------
  213.  *
  214.  * Fmt_Convert --
  215.  *
  216.  *    Convert data from one format to another.
  217.  *    See the man page for more details.
  218.  *
  219.  * Results:
  220.  *    Data is read from the input buffer using the input format
  221.  *    and written to the output buffer using the output format.
  222.  *    *inSizePtr contains the actual number of input bytes used
  223.  *    and *outSizePtr contains the actual number of output bytes used.
  224.  *
  225.  *    Returns:
  226.  *    FMT_OK            -- conversion successful.
  227.  *    FMT_CONTENT_ERROR     -- error in content string
  228.  *    FMT_INPUT_TOO_SMALL    -- size of input buffer is smaller than that
  229.  *                   indicated by content string
  230.  *    FMT_OUTPUT_TOO_SMALL    -- output buffer is too small
  231.  *    FMT_ILLEGAL_FORMAT    -- one of the formats is bad
  232.  *
  233.  * Side effects:
  234.  *    None.
  235.  *
  236.  *----------------------------------------------------------------------
  237.  */
  238.  
  239. int
  240. Fmt_Convert(contents, inFormat, inSizePtr, inBuf, outFormat, outSizePtr, outBuf)
  241.     char        *contents;    /* String describing contents of 
  242.                      * buffers. */
  243.     Fmt_Format        inFormat;    /* Data format of input buffer */
  244.     int            *inSizePtr;    /* Ptr to size of input buffer */
  245.     char        *inBuf;        /* Input buffer */
  246.     Fmt_Format        outFormat;    /* Data format of output buffer */
  247.     int            *outSizePtr;    /* Ptr to size of output buffer */
  248.     char        *outBuf;    /* Output buffer */
  249. {
  250.  
  251.     State    state;
  252.     int        status;
  253.  
  254.     if ((inFormat & 0x1000) != 0) {
  255.     inFormat &= ~0x1000;
  256.     } else {
  257.     inFormat = compat[inFormat];
  258.     }
  259.     if ((outFormat & 0x1000) != 0) {
  260.     outFormat &= ~0x1000;
  261.     } else {
  262.     outFormat = compat[outFormat];
  263.     }
  264.  
  265.     if (inFormat < 1 || inFormat > formatCount) {
  266.     return FMT_ILLEGAL_FORMAT;
  267.     } 
  268.     if (outFormat < 1 || outFormat > formatCount) {
  269.     return FMT_ILLEGAL_FORMAT;
  270.     } 
  271.     state.contPtr = contents;
  272.     state.inEndPtr = inBuf + *inSizePtr;
  273.     state.inPtr = inBuf;
  274.     state.inStartPtr = inBuf;
  275.     state.outEndPtr = outBuf + *outSizePtr;
  276.     state.outPtr = outBuf;
  277.     state.outStartPtr = outBuf;
  278.     state.inInfoPtr = &(formatInfo[inFormat-1]);
  279.     state.outInfoPtr = &(formatInfo[outFormat-1]);
  280.  
  281.     status = ConvertSequence(TRUE, -1, '\0', &state);
  282.  
  283.     *inSizePtr = (int) (state.inPtr - inBuf);
  284.     *outSizePtr = (int) (state.outPtr - outBuf);
  285.  
  286.     return status;
  287. }
  288.  
  289. /*
  290.  *----------------------------------------------------------------------
  291.  *
  292.  * Fmt_Size --
  293.  *    Compute the size of the data after conversion.
  294.  *    See the man page for more details.
  295.  *
  296.  * Results:
  297.  *    Data is read from the input buffer using the input format
  298.  *    and written to the output buffer using the output format.
  299.  *    *inSizePtr contains the actual number of input bytes used.
  300.  *    *outSizePtr contains the size of the input data after conversion.
  301.  *
  302.  *    Returns:
  303.  *    FMT_OK            -- size calculation successful.
  304.  *    FMT_CONTENT_ERROR     -- error in content string
  305.  *    FMT_INPUT_TOO_SMALL    -- size of input buffer is smaller than that
  306.  *                   indicated by content string
  307.  *    FMT_ILLEGAL_FORMAT    -- one of the formats is bad
  308.  *
  309.  * Side effects:
  310.  *    None.
  311.  *
  312.  *----------------------------------------------------------------------
  313.  */
  314.  
  315. int
  316. Fmt_Size(contents, inFormat, inSizePtr, outFormat, outSizePtr)
  317.     char        *contents;    /* String describing contents of 
  318.                      * buffers. */
  319.     Fmt_Format        inFormat;    /* Data format of input buffer */
  320.     int            *inSizePtr;    /* Ptr to size of input buffer */
  321.     Fmt_Format        outFormat;    /* Data format of output buffer */
  322.     int            *outSizePtr;    /* Ptr to size of output buffer */
  323. {
  324.  
  325.     State    state;
  326.     int        status;
  327.  
  328.     if ((inFormat & 0x1000) != 0) {
  329.     inFormat &= ~0x1000;
  330.     } else {
  331.     inFormat = compat[inFormat];
  332.     }
  333.     if ((outFormat & 0x1000) != 0) {
  334.     outFormat &= ~0x1000;
  335.     } else {
  336.     outFormat = compat[outFormat];
  337.     }
  338.  
  339.     if (inFormat < 1 || inFormat > formatCount) {
  340.     return FMT_ILLEGAL_FORMAT;
  341.     } 
  342.     if (outFormat < 1 || outFormat > formatCount) {
  343.     return FMT_ILLEGAL_FORMAT;
  344.     } 
  345.     state.contPtr = contents;
  346.     state.inEndPtr = (char *) *inSizePtr;
  347.     state.inPtr = NULL;
  348.     state.inStartPtr = NULL;
  349.     state.outEndPtr = NULL;
  350.     state.outPtr = NULL;
  351.     state.outStartPtr = NULL;
  352.     state.inInfoPtr = &(formatInfo[inFormat-1]);
  353.     state.outInfoPtr = &(formatInfo[outFormat-1]);
  354.  
  355.     status = ConvertSequence(FALSE, -1, '\0', &state);
  356.  
  357.     *inSizePtr = (int) (state.inPtr);
  358.     *outSizePtr = (int) (state.outPtr);
  359.  
  360.     return status;
  361. }
  362.  
  363. /*
  364.  *----------------------------------------------------------------------
  365.  *
  366.  * ConvertSequence --
  367.  *
  368.  *    The conversion process is broken up in a hierarchical manner.
  369.  *    At the leaves are the conversions of bytes, halfwords, words and 
  370.  *    doublewords. Structures and unions are converted by converting
  371.  *    their components. These may be leaves, or they may be nested
  372.  *    structures and unions. Sequences are collections of conversions
  373.  *    at the same nesting level. The initial content string represents
  374.  *    a sequence of conversions, as do the fields of a structure.
  375.  *    The conversion of sequences requires no special alignment like
  376.  *    the other types of conversion.
  377.  *
  378.  *    The doCopy and unionIndex parameters can be used to control the
  379.  *    conversion. If doCopy is FALSE then the output buffer is not
  380.  *    modified. If unionIndex is >= 0, then only one element of the
  381.  *    sequence will be copied into the output buffer (if doCopy is TRUE).
  382.  *    If unionIndex < 0 then the sequence is not the components of a
  383.  *    union so they are all copied (if doCopy is TRUE).  If we are
  384.  *    processing a union the pointers to the input and output buffers
  385.  *    will be adjusted as if the largest element in the sequence had been
  386.  *    copied. For example, the union "(0bw)" should have the byte copied,
  387.  *    but the size of the union is 4 bytes. Keeping track of the largest
  388.  *    component allows the pointers to be advanced to the end of the
  389.  *    union.
  390.  *
  391.  * Results:
  392.  *    The state structure is modified to reflect the current state of
  393.  *    the conversion. Data may be copied from the input buffer to
  394.  *    the output buffer.
  395.  *
  396.  *    Returns:
  397.  *    FMT_OK            -- conversion successful.
  398.  *    FMT_CONTENT_ERROR     -- error in content string
  399.  *    FMT_INPUT_TOO_SMALL    -- size of input buffer is smaller than that
  400.  *                   indicated by content string
  401.  *    FMT_OUTPUT_TOO_SMALL    -- output buffer is too small
  402.  *
  403.  * Side effects:
  404.  *    None.
  405.  *
  406.  *----------------------------------------------------------------------
  407.  */
  408.  
  409. static int
  410. ConvertSequence(doCopy, unionIndex, openChar, statePtr)
  411.     Boolean        doCopy;        /* FALSE => don't modify the
  412.                      * output buffer. */
  413.     int            unionIndex;    /* If >= 0 then we are doing a union
  414.                      * so only copy this element and set
  415.                      * pointers to max of elements. */
  416.     char        openChar;    /* The character that started the 
  417.                      * sequence. */
  418.     register State    *statePtr;    /* Current state of conversion */
  419. {
  420.     register char     *contPtr;
  421.     int            status;
  422.     int            repCount;
  423.     char        *afterPtr;
  424.     int            curIndex;
  425.     char        *maxInPtr = (char *)NIL;
  426.     char        *maxOutPtr = (char *)NIL;
  427.     Boolean        doSubCopy;
  428.     char        *startInPtr = (char *)NIL;
  429.     char         *startOutPtr = (char *)NIL;
  430.  
  431.     status = FMT_OK;
  432.     curIndex = 0;
  433.     /*
  434.      * If we are doing a union keep track of where we started and the
  435.      * maximum  pointer values.
  436.      */
  437.     if (unionIndex >= 0) {
  438.     maxInPtr = statePtr->inPtr;
  439.     startInPtr = statePtr->inPtr;
  440.     maxOutPtr = statePtr->outPtr;
  441.     startOutPtr = statePtr->outPtr;
  442.     }
  443.     contPtr = statePtr->contPtr;
  444.     while (*contPtr != '\0') {
  445.     doSubCopy = doCopy && ((unionIndex < 0) || (unionIndex == curIndex));
  446.     switch (*contPtr) {
  447.         case '{' :
  448.         status = ConvertStruct(doSubCopy, unionIndex >= 0,  
  449.                 statePtr, &repCount);
  450.         break;
  451.         case '(' :
  452.         status = ConvertUnion(doSubCopy, unionIndex >= 0,  
  453.                 statePtr, &repCount);
  454.         break;
  455.         case '}' :
  456.         if (openChar != '{') {
  457.             return FMT_CONTENT_ERROR;
  458.         } else {
  459.             statePtr->contPtr = contPtr+1;
  460.             goto exit;
  461.         }
  462.         break;
  463.         case ')' :
  464.         if (openChar != '(') {
  465.             return FMT_CONTENT_ERROR;
  466.         } else {
  467.             statePtr->contPtr = contPtr+1;
  468.             goto exit;
  469.         }
  470.         break;
  471.         default : 
  472.         repCount = 1;
  473.         contPtr++;
  474.         /*
  475.          * Suck up strings of the same character. If we are doing
  476.          * a union we can't do this because they represent different
  477.          * components, not repeated data types within the same
  478.          * component. 
  479.          */
  480.         if (unionIndex < 0) {
  481.             while (*contPtr == *(contPtr-1)) {
  482.             contPtr++;
  483.             repCount++;
  484.             }
  485.         }
  486.         /*
  487.          * Get the repeat count if there is one.
  488.          */
  489.         if ((*contPtr >= '0') && (*contPtr <= '9')) {
  490.             repCount += strtoul(contPtr, &afterPtr, 10) - 1;
  491.             if (contPtr == afterPtr) {
  492.             return FMT_CONTENT_ERROR;
  493.             }
  494.         } else if (*contPtr == '*') {
  495.             repCount = -1;
  496.             afterPtr = contPtr + 1;
  497.         } else {
  498.             afterPtr = contPtr;
  499.         }
  500.         contPtr--;
  501.         if (repCount != 0) {
  502.             switch(*contPtr) {
  503.             case 'b' :
  504.                 status = ConvertByte(doSubCopy, 
  505.                         repCount, statePtr);
  506.                 break;
  507.             case 'h' :
  508.                 status = ConvertHalfWord(doSubCopy,  
  509.                         repCount, statePtr);
  510.                 break;
  511.             case 'w' :
  512.                 status = ConvertWord(doSubCopy, 
  513.                         repCount, statePtr);
  514.                 break;
  515.             case 'd' :
  516.                 status = ConvertDoubleWord(doSubCopy, 
  517.                         repCount, statePtr);
  518.                 break;
  519.             default :
  520.                 return FMT_CONTENT_ERROR;
  521.                 break;
  522.             }
  523.         }
  524.         contPtr = statePtr->contPtr = afterPtr;
  525.     }
  526.     if (status) {
  527.         return status;
  528.     }
  529.     curIndex += 1;
  530.     contPtr = statePtr->contPtr;
  531.     /*
  532.      * Save the max and reset the buffer pointers.
  533.      */
  534.     if (unionIndex >= 0) {
  535.         maxInPtr = MAX(maxInPtr, statePtr->inPtr);
  536.         maxOutPtr = MAX(maxOutPtr, statePtr->outPtr);
  537.         statePtr->inPtr = startInPtr;
  538.         statePtr->outPtr = startOutPtr;
  539.     }
  540.     }
  541. exit:
  542.     if (unionIndex >= 0) {
  543.     statePtr->inPtr = maxInPtr;
  544.     statePtr->outPtr = maxOutPtr;
  545.     }
  546.     return status;
  547. }
  548.  
  549.  
  550. /*
  551.  *----------------------------------------------------------------------
  552.  *
  553.  * ConvertStruct --
  554.  *
  555.  *    Process a structure conversion. Unlike simple data types, we don't
  556.  *    recognize strings of repeated structures. If the same structure is
  557.  *    repeated twice then we parse it twice. If a structure definition
  558.  *    is followed by a repeat count, then we parse the definition multiple
  559.  *    times also. It's too hard to do it differently. Also, since structure
  560.  *    definitions are variable length the repeat count is not passed in
  561.  *    by the calling procedure.  We pass it out instead.
  562.  *    
  563.  *    The doingUnion flag indicates that the structure is a member of a
  564.  *    union. If it is followed by a repeat count then only convert one
  565.  *    of them.
  566.  *
  567.  * Results:
  568.  *    Contents of the state record are modified to represent the
  569.  *    current state of the conversion. The content pointer is advanced
  570.  *    over the description of the structure and its rep count. 
  571.  *    inPtr and outPtr are advanced.
  572.  *    
  573.  *    Returns:
  574.  *    FMT_OK            -- conversion successful.
  575.  *    FMT_CONTENT_ERROR     -- error in content string
  576.  *    FMT_INPUT_TOO_SMALL    -- size of input buffer is smaller than that
  577.  *                   indicated by content string
  578.  *    FMT_OUTPUT_TOO_SMALL    -- output buffer is too small
  579.  *
  580.  * Side effects:
  581.  *    None.
  582.  *
  583.  *----------------------------------------------------------------------
  584.  */
  585.  
  586. static int
  587. ConvertStruct(doCopy, doingUnion, statePtr, repCountPtr)
  588.     Boolean        doCopy;     /* FALSE => don't modify output
  589.                      * buffer. */
  590.     Boolean        doingUnion;    /* TRUE => ignore rep count and only
  591.                      * convert one. */
  592.     register State    *statePtr;    /* Current state of conversion */
  593.     int            *repCountPtr;    /* Number of repetitions. */
  594. {
  595.  
  596.     char        *contPtr;
  597.     char        *afterPtr;
  598.     int            status;
  599.     int            repCount;
  600.     register int    count;
  601.     int            inAlign;
  602.     int            outAlign;
  603.  
  604.     afterPtr = statePtr->contPtr;
  605.     status = CalcComplexAlign(statePtr, &afterPtr, &repCount, &inAlign, 
  606.             &outAlign);
  607.     if (status) {
  608.     return status;
  609.     }
  610.     if (doingUnion) {
  611.     count = 1;
  612.     } else {
  613.     count = repCount;
  614.     }
  615.     contPtr = statePtr->contPtr + 1;
  616.     for (; count != 0; count--) {
  617.     AlignPointer(inAlign, statePtr->inStartPtr, statePtr->inPtr);
  618.     AlignPointer(outAlign, statePtr->outStartPtr, statePtr->outPtr);
  619.     /*
  620.      * If the structure is followed by a '*' and we are at the end of
  621.      * the input buffer then bail out.
  622.      */
  623.     if ((count < 0) && (statePtr->inPtr == statePtr->inEndPtr)) {
  624.         break;
  625.     }
  626.     statePtr->contPtr = contPtr;
  627.     status = ConvertSequence(doCopy, -1, '{', statePtr);
  628.     if (status) {
  629.         return status;
  630.     }
  631.     }
  632.     /*
  633.      * Structure size is always a multiple of the alignment.
  634.      */
  635.     AlignPointer(inAlign, statePtr->inStartPtr, statePtr->inPtr);
  636.     AlignPointer(outAlign, statePtr->outStartPtr, statePtr->outPtr);
  637.     statePtr->contPtr = afterPtr;
  638.     *repCountPtr = repCount;
  639.     return status;
  640.  
  641. }
  642.  
  643.  
  644. /*
  645.  *----------------------------------------------------------------------
  646.  *
  647.  * ConvertUnion --
  648.  *
  649.  *    Process a union conversion. The comments for ConvertStruct apply.
  650.  *    The opening parenthesis of a union definition is followed by the
  651.  *    discriminator (index of the element to be copied). This discriminator
  652.  *    is passed to ConvertSequence so only that element is copied.
  653.  *
  654.  * Results:
  655.  *    Contents of the state record are modified to represent the
  656.  *    current state of the conversion. The content pointer is advanced
  657.  *    over the description of the union and its rep count. 
  658.  *    inPtr and outPtr are advanced.
  659.  *
  660.  *    Returns:
  661.  *    FMT_OK            -- conversion successful.
  662.  *    FMT_CONTENT_ERROR     -- error in content string
  663.  *    FMT_INPUT_TOO_SMALL    -- size of input buffer is smaller than that
  664.  *                   indicated by content string
  665.  *    FMT_OUTPUT_TOO_SMALL    -- output buffer is too small
  666.  *
  667.  * Side effects:
  668.  *    None.
  669.  *
  670.  *----------------------------------------------------------------------
  671.  */
  672.  
  673. static int
  674. ConvertUnion(doCopy, doingUnion, statePtr, repCountPtr)
  675.     Boolean        doCopy;     /* FALSE => don't modify output
  676.                      * buffer. */
  677.     Boolean        doingUnion;    /* TRUE => ignore rep count and only
  678.                      * convert one. */
  679.     register State    *statePtr;    /* Current state of conversion */
  680.     int            *repCountPtr;    /* Number of repetitions. */
  681. {
  682.  
  683.     char        *contPtr;
  684.     char        *afterPtr;
  685.     int            status;
  686.     int            repCount;
  687.     register int    count;
  688.     char        *tempPtr;
  689.     int            index;
  690.     int            inAlign;
  691.     int            outAlign;
  692.  
  693.     afterPtr = statePtr->contPtr;
  694.     status = CalcComplexAlign(statePtr, &afterPtr, &repCount, &inAlign, 
  695.             &outAlign);
  696.     if (status) {
  697.     return status;
  698.     }
  699.     if (doingUnion) {
  700.     count = 1;
  701.     } else {
  702.     count = repCount;
  703.     }
  704.     contPtr = statePtr->contPtr + 1;
  705.     /*
  706.      * Get the discriminator.
  707.      */
  708.     if ((*contPtr >= '0') && (*contPtr <= '9')) {
  709.     index = strtoul(contPtr, &tempPtr, 10);
  710.     if (contPtr == tempPtr) {
  711.         return FMT_CONTENT_ERROR;
  712.     }
  713.     } else {
  714.     return FMT_CONTENT_ERROR;
  715.     }
  716.     contPtr = tempPtr;
  717.     for (; count != 0; count--) {
  718.     AlignPointer(inAlign, statePtr->inStartPtr, statePtr->inPtr);
  719.     AlignPointer(outAlign, statePtr->outStartPtr, statePtr->outPtr);
  720.     /*
  721.      * If the union is followed by a '*' and we are at the end of
  722.      * the input buffer then bail out.
  723.      */
  724.     if ((count < 0) && (statePtr->inPtr == statePtr->inEndPtr)) {
  725.         break;
  726.     }
  727.     statePtr->contPtr = contPtr;
  728.     status = ConvertSequence(doCopy, index, '(', statePtr);
  729.     if (status) {
  730.         return status;
  731.     }
  732.     }
  733.     AlignPointer(inAlign, statePtr->inStartPtr, statePtr->inPtr);
  734.     AlignPointer(outAlign, statePtr->outStartPtr, statePtr->outPtr);
  735.     statePtr->contPtr = afterPtr;
  736.     *repCountPtr = repCount;
  737.     return status;
  738. }
  739.  
  740.  
  741. /*
  742.  *----------------------------------------------------------------------
  743.  *
  744.  * ConvertByte --
  745.  *
  746.  *    If doCopy is TRUE, then copy bytes from the input buffer to the
  747.  *    output buffer. Otherwise just advance the buffer pointers.
  748.  *    If either buffer is too small then return an error. An exception
  749.  *     is made if the pointer to the end of the output buffer is NULL.
  750.  *    This indicates that there isn't an output buffer.
  751.  *
  752.  * Results:
  753.  *    The contents of the state structure are modified to reflect the
  754.  *    current state of the conversion. The input and output pointers
  755.  *    are aligned and advanced repCount bytes.
  756.  *
  757.  *    Returns:
  758.  *    FMT_OK            -- conversion successful.
  759.  *    FMT_INPUT_TOO_SMALL    -- input buffer is too small
  760.  *    FMT_OUTPUT_TOO_SMALL    -- output buffer is too small
  761.  *
  762.  * Side effects:
  763.  *    None.
  764.  *
  765.  *----------------------------------------------------------------------
  766.  */
  767.  
  768. static int
  769. ConvertByte(doCopy, repCount, statePtr)
  770.     Boolean        doCopy;        /* TRUE => modify output buffer. */
  771.     int            repCount;    /* Number of bytes to copy. */
  772.     State        *statePtr;    /* Current state of conversion. */
  773. {
  774.     register int    i;
  775.     register char    *inPtr;
  776.     register char    *outPtr;
  777.     int            status;
  778.  
  779.     inPtr = statePtr->inPtr;
  780.     outPtr = statePtr->outPtr;
  781.     status = FMT_OK;
  782.  
  783.     AlignPointer(statePtr->inInfoPtr->bAlign, statePtr->inStartPtr, inPtr);
  784.     AlignPointer(statePtr->outInfoPtr->bAlign, statePtr->outStartPtr, outPtr);
  785.  
  786.     if (repCount > 0) {
  787.     if (inPtr + repCount  > statePtr->inEndPtr) {
  788.         status = FMT_INPUT_TOO_SMALL;
  789.         repCount = statePtr->inEndPtr - inPtr;
  790.     }
  791.     } else {
  792.     repCount = statePtr->inEndPtr - inPtr;
  793.     }
  794.     if (statePtr->outEndPtr != NULL && 
  795.     outPtr + repCount > statePtr->outEndPtr) {
  796.     status = FMT_OUTPUT_TOO_SMALL;
  797.     repCount = statePtr->outEndPtr - outPtr;
  798.     }
  799.     if (doCopy) {
  800.     for (i = 0; i < repCount; i++) {
  801.         *outPtr = *inPtr;
  802.         outPtr++;
  803.         inPtr++;
  804.     }
  805.     } else {
  806.     inPtr += repCount;
  807.     outPtr += repCount;
  808.     }
  809.  
  810.     statePtr->inPtr = inPtr;
  811.     statePtr->outPtr = outPtr;
  812.     return status;
  813. }
  814.  
  815.  
  816. /*
  817.  *----------------------------------------------------------------------
  818.  *
  819.  * ConvertHalfWord --
  820.  *
  821.  *    If doCopy is TRUE, then copy halfwords from the input buffer to the
  822.  *    output buffer. Otherwise just advance the buffer pointers.
  823.  *    If either buffer is too small then return an error. An exception
  824.  *     is made if the pointer to the end of the output buffer is NULL.
  825.  *    This indicates that there isn't an output buffer.
  826.  *
  827.  * Results:
  828.  *    The contents of the state structure are modified to reflect the
  829.  *    current state of the conversion. The input and output pointers
  830.  *    are aligned and advanced repCount halfwords.
  831.  *
  832.  *    Returns:
  833.  *    FMT_OK            -- conversion successful.
  834.  *    FMT_INPUT_TOO_SMALL    -- input buffer is too small
  835.  *    FMT_OUTPUT_TOO_SMALL    -- output buffer is too small
  836.  *
  837.  * Side effects:
  838.  *    None.
  839.  *
  840.  *----------------------------------------------------------------------
  841.  */
  842.  
  843. static int
  844. ConvertHalfWord(doCopy, repCount, statePtr)
  845.     Boolean        doCopy;        /* TRUE => modify output buffer. */
  846.     int            repCount;    /* Number of halfwords to copy. */
  847.     State        *statePtr;    /* Current state of conversion. */
  848. {
  849.     register int    i;
  850.     register char    *inPtr;
  851.     register char    *outPtr;
  852.     int            status;
  853.  
  854.     inPtr = statePtr->inPtr;
  855.     outPtr = statePtr->outPtr;
  856.     status = FMT_OK;
  857.  
  858.  
  859.     AlignPointer(statePtr->inInfoPtr->hAlign, statePtr->inStartPtr, inPtr);
  860.     AlignPointer(statePtr->outInfoPtr->hAlign, statePtr->outStartPtr, outPtr);
  861.  
  862.     if (repCount > 0) {
  863.     if (inPtr + repCount * 2  > statePtr->inEndPtr) {
  864.         status = FMT_INPUT_TOO_SMALL;
  865.         repCount = (((int) statePtr->inEndPtr) - ((int) inPtr)) / 2;
  866.     }
  867.     } else if (repCount < 0) {
  868.     repCount = (((int) statePtr->inEndPtr) - ((int) inPtr)) / 2;
  869.     } else {
  870.     return status;
  871.     }
  872.     if (statePtr->outEndPtr != NULL && 
  873.         outPtr + repCount * 2 > statePtr->outEndPtr) {
  874.     status = FMT_OUTPUT_TOO_SMALL;
  875.     repCount = (((int) statePtr->outEndPtr) - ((int) repCount)) / 2;
  876.     }
  877.     if (doCopy) {
  878.     if (statePtr->inInfoPtr->byteOrder == 
  879.         statePtr->outInfoPtr->byteOrder) { 
  880.  
  881.         for (i = 0; i < repCount; i++) {
  882.         outPtr[0] = inPtr[0];
  883.         outPtr[1] = inPtr[1];
  884.         inPtr += 2;
  885.         outPtr += 2;
  886.         }
  887.     } else {
  888.         for (i = 0; i < repCount; i++) {
  889.         outPtr[0] = inPtr[1];
  890.         outPtr[1] = inPtr[0];
  891.         inPtr += 2;
  892.         outPtr += 2;
  893.         }
  894.     }
  895.     } else {
  896.     inPtr += repCount * 2;
  897.     outPtr += repCount * 2;
  898.     }
  899.     statePtr->inPtr = inPtr;
  900.     statePtr->outPtr = outPtr;
  901.     return status;
  902. }
  903.  
  904. /*
  905.  *----------------------------------------------------------------------
  906.  *
  907.  * ConvertWord --
  908.  *
  909.  *    If doCopy is TRUE, then copy words from the input buffer to the
  910.  *    output buffer. Otherwise just advance the buffer pointers.
  911.  *    If either buffer is too small then return an error. An exception
  912.  *     is made if the pointer to the end of the output buffer is NULL.
  913.  *    This indicates that there isn't an output buffer.
  914.  *
  915.  * Results:
  916.  *    The contents of the state structure are modified to reflect the
  917.  *    current state of the conversion. The input and output pointers
  918.  *    are aligned and advanced repCount words.
  919.  *
  920.  *    Returns:
  921.  *    FMT_OK            -- conversion successful.
  922.  *    FMT_INPUT_TOO_SMALL    -- input buffer is too small
  923.  *    FMT_OUTPUT_TOO_SMALL    -- output buffer is too small
  924.  *
  925.  * Side effects:
  926.  *    None.
  927.  *
  928.  *----------------------------------------------------------------------
  929.  */
  930.  
  931. static int
  932. ConvertWord(doCopy, repCount, statePtr)
  933.     Boolean        doCopy;        /* TRUE => modify output buffer. */
  934.     int            repCount;    /* Number of words to copy. */
  935.     State        *statePtr;    /* Current state of conversion. */
  936. {
  937.     register int    i;
  938.     register char    *inPtr;
  939.     register char    *outPtr;
  940.     int            status;
  941.  
  942.     inPtr = statePtr->inPtr;
  943.     outPtr = statePtr->outPtr;
  944.     status = FMT_OK;
  945.  
  946.     AlignPointer(statePtr->inInfoPtr->wAlign, statePtr->inStartPtr, inPtr);
  947.     AlignPointer(statePtr->outInfoPtr->wAlign, statePtr->outStartPtr, outPtr);
  948.  
  949.     if (repCount > 0) {
  950.     if (inPtr + repCount * 4 > statePtr->inEndPtr) {
  951.         status = FMT_INPUT_TOO_SMALL;
  952.         repCount = (((int) statePtr->inEndPtr) - ((int) inPtr)) / 4;
  953.     }
  954.     } else if (repCount < 0) {
  955.     repCount = (((int) statePtr->inEndPtr) - ((int) inPtr)) / 4;
  956.     } else {
  957.     return status;
  958.     }
  959.     if (statePtr->outEndPtr != NULL && 
  960.         outPtr + repCount * 4 > statePtr->outEndPtr) {
  961.     status = FMT_OUTPUT_TOO_SMALL;
  962.     repCount = ((int) statePtr->outEndPtr - ((int) outPtr)) / 4;
  963.     }
  964.     if (doCopy) {
  965.     if (statePtr->inInfoPtr->byteOrder == 
  966.         statePtr->outInfoPtr->byteOrder) { 
  967.         for (i = 0; i < repCount; i++) {
  968.         outPtr[0] = inPtr[0];
  969.         outPtr[1] = inPtr[1];
  970.         outPtr[2] = inPtr[2];
  971.         outPtr[3] = inPtr[3];
  972.         inPtr += 4;
  973.         outPtr += 4;
  974.         }
  975.     } else {
  976.         for (i = 0; i < repCount; i++) {
  977.         outPtr[0] = inPtr[3];
  978.         outPtr[1] = inPtr[2];
  979.         outPtr[2] = inPtr[1];
  980.         outPtr[3] = inPtr[0];
  981.         inPtr += 4;
  982.         outPtr += 4;
  983.         }
  984.     }
  985.     } else {
  986.     inPtr += repCount * 4;
  987.     outPtr += repCount * 4;
  988.     }
  989.     statePtr->inPtr = inPtr;
  990.     statePtr->outPtr = outPtr;
  991.     return status;
  992. }
  993.  
  994. /*
  995.  *----------------------------------------------------------------------
  996.  *
  997.  * ConvertDoubleWord --
  998.  *
  999.  *    If doCopy is TRUE, then copy doublewords from the input buffer to
  1000.  *    the output buffer. Otherwise just advance the buffer pointers.  If
  1001.  *    either buffer is too small then return an error. An exception is
  1002.  *    made if the pointer to the end of the output buffer is NULL.  This
  1003.  *    indicates that there isn't an output buffer.
  1004.  *
  1005.  * Results:
  1006.  *    The contents of the state structure are modified to reflect the
  1007.  *    current state of the conversion. The input and output pointers
  1008.  *    are aligned and advanced repCount doublewords.
  1009.  *    
  1010.  *    Returns:
  1011.  *    FMT_OK            -- conversion successful.
  1012.  *    FMT_INPUT_TOO_SMALL    -- input buffer is too small
  1013.  *    FMT_OUTPUT_TOO_SMALL    -- output buffer is too small
  1014.  *
  1015.  * Side effects:
  1016.  *    None.
  1017.  *
  1018.  *----------------------------------------------------------------------
  1019.  */
  1020.  
  1021. static int
  1022. ConvertDoubleWord(doCopy, repCount, statePtr)
  1023.     Boolean        doCopy;        /* TRUE => modify output buffer. */
  1024.     int            repCount;    /* Number of doublewords to copy. */
  1025.     State        *statePtr;    /* Current state of conversion. */
  1026. {
  1027.     register int    i;
  1028.     register char    *inPtr;
  1029.     register char    *outPtr;
  1030.     int            status;
  1031.  
  1032.     inPtr = statePtr->inPtr;
  1033.     outPtr = statePtr->outPtr;
  1034.     status = FMT_OK;
  1035.  
  1036.     AlignPointer(statePtr->inInfoPtr->dAlign, statePtr->inStartPtr, inPtr);
  1037.     AlignPointer(statePtr->outInfoPtr->dAlign, statePtr->outStartPtr, outPtr);
  1038.  
  1039.     if (repCount > 0) {
  1040.     if (inPtr + repCount * 8 > statePtr->inEndPtr) {
  1041.         status = FMT_INPUT_TOO_SMALL;
  1042.         repCount = (((int) statePtr->inEndPtr) - ((int) inPtr)) / 8;
  1043.     }
  1044.     } else if (repCount < 0) {
  1045.     repCount = (((int) statePtr->inEndPtr) - ((int) inPtr)) / 8;
  1046.     } else {
  1047.     return status;
  1048.     }
  1049.     if (statePtr->outEndPtr != NULL && 
  1050.         outPtr + repCount * 8 > statePtr->outEndPtr) {
  1051.     status = FMT_OUTPUT_TOO_SMALL;
  1052.     repCount = (((int) statePtr->outEndPtr) - ((int) outPtr)) / 8;
  1053.     }
  1054.     if (doCopy) {
  1055.     if (statePtr->inInfoPtr->byteOrder == 
  1056.         statePtr->outInfoPtr->byteOrder) { 
  1057.  
  1058.         for (i = 0; i < repCount; i++) {
  1059.         outPtr[0] = inPtr[0];
  1060.         outPtr[1] = inPtr[1];
  1061.         outPtr[2] = inPtr[2];
  1062.         outPtr[3] = inPtr[3];
  1063.         outPtr[4] = inPtr[4];
  1064.         outPtr[5] = inPtr[5];
  1065.         outPtr[6] = inPtr[6];
  1066.         outPtr[7] = inPtr[7];
  1067.         inPtr += 8;
  1068.         outPtr += 8;
  1069.         }
  1070.     } else {
  1071.         for (i = 0; i < repCount; i++) {
  1072.         outPtr[0] = inPtr[7];
  1073.         outPtr[1] = inPtr[6];
  1074.         outPtr[2] = inPtr[5];
  1075.         outPtr[3] = inPtr[4];
  1076.         outPtr[4] = inPtr[3];
  1077.         outPtr[5] = inPtr[2];
  1078.         outPtr[6] = inPtr[1];
  1079.         outPtr[7] = inPtr[0];
  1080.         inPtr += 8;
  1081.         outPtr += 8;
  1082.         }
  1083.     }
  1084.     } else {
  1085.     inPtr += repCount * 8;
  1086.     outPtr += repCount * 8;
  1087.     }
  1088.     statePtr->inPtr = inPtr;
  1089.     statePtr->outPtr = outPtr;
  1090.     return status;
  1091. }
  1092.  
  1093. /*
  1094.  *----------------------------------------------------------------------
  1095.  *
  1096.  * CalcComplexAlign --
  1097.  *
  1098.  *    Calculate the alignment of a structure or a union. The alignment
  1099.  *    is the maximum of the alignment specified by the format and the
  1100.  *    alignments of the fields. The repeat count is read and returned
  1101.  *    in *repCountPtr. If the data type is followed by '*' then -1 is
  1102.  *    returned as the repeat count.
  1103.  *
  1104.  * Results:
  1105.  *    *contPtrPtr points to the first character after the data type
  1106.  *    definition and repeat count. *inAlignPtr contains the alignment
  1107.  *    for the in format, and *outAlignPtr contains the alignment for the
  1108.  *    out format. *repCountPtr contains the repeat count.
  1109.  *
  1110.  *    Returns:
  1111.  *    FMT_OK            -- conversion successful.
  1112.  *    FMT_CONTENT_ERROR     -- error in content string
  1113.  *
  1114.  * Side effects:
  1115.  *    None.
  1116.  *
  1117.  *----------------------------------------------------------------------
  1118.  */
  1119.  
  1120. static int
  1121. CalcComplexAlign(statePtr, contPtrPtr, repCountPtr, inAlignPtr, outAlignPtr)
  1122.     State         *statePtr;    /* Current state of conversion. */
  1123.     char        **contPtrPtr;    /* Ptr to ptr to content string */
  1124.     int            *repCountPtr;    /* Ptr to repeat count. */
  1125.     int            *inAlignPtr;    /* Ptr to in alignment. */
  1126.     int            *outAlignPtr;    /* Ptr to out alignment. */
  1127. {
  1128.     int                inAlign = 0; /* dummy initial value */
  1129.     int                outAlign = 0; /* dummy initial value */
  1130.     register char        *contPtr;
  1131.     Boolean            doingUnion = FALSE; /* dummy initial value */
  1132.     char            lastChar;
  1133.     int                status;
  1134.     int                repCount;
  1135.     char            *tempPtr;
  1136.     register FormatInfo        *inInfoPtr;
  1137.     register FormatInfo        *outInfoPtr;
  1138.  
  1139.     status = FMT_OK;
  1140.     contPtr = *contPtrPtr;
  1141.     inInfoPtr = statePtr->inInfoPtr;
  1142.     outInfoPtr = statePtr->outInfoPtr;
  1143.     switch (*contPtr) {
  1144.     case '{' :
  1145.         inAlign = inInfoPtr->structMinAlign;
  1146.         outAlign = outInfoPtr->structMinAlign;
  1147.         doingUnion = FALSE;
  1148.         break;
  1149.     case '(' :
  1150.         inAlign = inInfoPtr->unionMinAlign;
  1151.         outAlign = outInfoPtr->unionMinAlign;
  1152.         doingUnion = TRUE;
  1153.         break;
  1154.     default :
  1155.         panic("Fmt: Internal error: CalcComplexAlign called improperly.\n");
  1156.     }
  1157.     contPtr++;
  1158.     lastChar = '\0';
  1159.     while (*contPtr != '\0') {
  1160.     if (*contPtr == lastChar) {
  1161.         contPtr++;
  1162.         continue;
  1163.     }
  1164.     lastChar = *contPtr;
  1165.     if ((*contPtr >= '0') && (*contPtr <= '9')) {
  1166.         contPtr++;
  1167.         continue;
  1168.     }
  1169.     switch (*contPtr) {
  1170.         case 'b':
  1171.         inAlign = MAX(inAlign, inInfoPtr->bAlign);
  1172.         outAlign = MAX(outAlign, outInfoPtr->bAlign);
  1173.         contPtr++;
  1174.         break;
  1175.         case 'h':
  1176.         inAlign = MAX(inAlign, inInfoPtr->hAlign);
  1177.         outAlign = MAX(outAlign, outInfoPtr->hAlign);
  1178.         contPtr++;
  1179.         break;
  1180.         case 'w':
  1181.         inAlign = MAX(inAlign, inInfoPtr->wAlign);
  1182.         outAlign = MAX(outAlign, outInfoPtr->wAlign);
  1183.         contPtr++;
  1184.         break;
  1185.         case 'd':
  1186.         inAlign = MAX(inAlign, inInfoPtr->dAlign);
  1187.         outAlign = MAX(outAlign, outInfoPtr->dAlign);
  1188.         contPtr++;
  1189.         break;
  1190.         case '(':
  1191.         case '{': {
  1192.         int dummy;
  1193.         int tempInAlign;
  1194.         int tempOutAlign;
  1195.         char *tempContPtr;
  1196.         tempContPtr = contPtr;
  1197.         status = CalcComplexAlign(statePtr, &tempContPtr, &dummy, 
  1198.                 &tempInAlign, &tempOutAlign);
  1199.         if (status) {
  1200.             return status;
  1201.         }
  1202.         inAlign = MAX(inAlign, tempInAlign);
  1203.         outAlign = MAX(outAlign, tempOutAlign);
  1204.         contPtr = tempContPtr;
  1205.         lastChar = '\0';
  1206.         break;
  1207.         }
  1208.         case ')':
  1209.         if (!doingUnion) {
  1210.             return FMT_CONTENT_ERROR;
  1211.         }
  1212.         contPtr++;
  1213.         goto exit;
  1214.         break;
  1215.         case '}':
  1216.         if (doingUnion) {
  1217.             return FMT_CONTENT_ERROR;
  1218.         }
  1219.         contPtr++;
  1220.         goto exit;
  1221.         break;
  1222.         case '*' :
  1223.         contPtr++;
  1224.         break;
  1225.         default :
  1226.         return FMT_CONTENT_ERROR;
  1227.         break;
  1228.     }
  1229.     }
  1230.     return FMT_CONTENT_ERROR;
  1231. exit :
  1232.     /*
  1233.      * Parse the repeat count.
  1234.      */
  1235.     if ((*contPtr >= '0') && (*contPtr <= '9')) {
  1236.     repCount = strtoul(contPtr, &tempPtr, 10);
  1237.     if (contPtr == tempPtr) {
  1238.         return FMT_CONTENT_ERROR;
  1239.     }
  1240.     contPtr = tempPtr;
  1241.     } else if (*contPtr == '*') {
  1242.     repCount = -1;
  1243.     contPtr++;
  1244.     } else {
  1245.     repCount = 1;
  1246.     }
  1247.     *repCountPtr = repCount;
  1248.     *contPtrPtr = contPtr;
  1249.     *inAlignPtr = inAlign;
  1250.     *outAlignPtr = outAlign;
  1251.     return status;
  1252. }
  1253.  
  1254. @
  1255.  
  1256.  
  1257. 1.8
  1258. log
  1259. @Use function prototypes.  Lint.
  1260. @
  1261. text
  1262. @d19 1
  1263. a19 1
  1264. static char rcsid[] = "$Header: /sprite/src/lib/c/etc/RCS/fmt.c,v 1.7 90/07/25 16:51:51 douglis Exp Locker: kupfer $ SPRITE (Berkeley)";
  1265. d283 1
  1266. d286 1
  1267. @
  1268.  
  1269.  
  1270. 1.7
  1271. log
  1272. @added symmetry
  1273. @
  1274. text
  1275. @d19 1
  1276. a19 1
  1277. static char rcsid[] = "$Header: /sprite/src/lib/c/etc/RCS/fmt.c,v 1.6 90/01/30 23:11:59 jhh Exp $ SPRITE (Berkeley)";
  1278. d28 1
  1279. d105 17
  1280. a121 8
  1281. static int    ConvertSequence();
  1282. static int    ConvertStruct();
  1283. static int    ConvertUnion();
  1284. static int    ConvertByte();
  1285. static int    ConvertHalfWord();
  1286. static int    ConvertWord();
  1287. static int    ConvertDoubleWord();
  1288. static int    CalcComplexAlign();
  1289. a122 2
  1290. extern void    panic();
  1291.  
  1292. d358 2
  1293. a359 2
  1294.     char        *maxInPtr;
  1295.     char        *maxOutPtr;
  1296. d361 2
  1297. a362 2
  1298.     char        *startInPtr;
  1299.     char         *startOutPtr;
  1300. d1061 2
  1301. a1062 2
  1302.     int                inAlign;
  1303.     int                outAlign;
  1304. d1064 1
  1305. a1064 1
  1306.     Boolean            doingUnion;
  1307. @
  1308.  
  1309.  
  1310. 1.6
  1311. log
  1312. @now handles unaligned buffers, both input and output
  1313. @
  1314. text
  1315. @d19 1
  1316. a19 1
  1317. static char rcsid[] = "$Header: /sprite/src/lib/c/etc/RCS/fmt.c,v 1.5 90/01/30 11:27:03 jhh Exp $ SPRITE (Berkeley)";
  1318. d72 1
  1319. @
  1320.  
  1321.  
  1322. 1.5
  1323. log
  1324. @doubles weren't swapped properly
  1325. @
  1326. text
  1327. @d19 1
  1328. a19 1
  1329. static char rcsid[] = "$Header: /sprite/src/lib/c/etc/RCS/fmt.c,v 1.4 90/01/26 11:53:41 douglis Exp Locker: jhh $ SPRITE (Berkeley)";
  1330. d86 1
  1331. d89 1
  1332. d117 13
  1333. a129 8
  1334.  * Macro to increment a pointer to the given alignment. If pointer is
  1335.  * not aligned properly then mask off low bits and add alignment.
  1336.  */
  1337.  
  1338. #define AlignPointer(align, ptr) {                    \
  1339.     if (((align) != 1) && (((int)(ptr)) & ((align) -1))) {        \
  1340.     (ptr) = (char *) (((int)(ptr)) & ~((align) -1)) + (align);     \
  1341.     }                                     \
  1342. d200 1
  1343. d203 1
  1344. d541 2
  1345. a542 2
  1346.     AlignPointer(inAlign, statePtr->inPtr);
  1347.     AlignPointer(outAlign, statePtr->outPtr);
  1348. d559 2
  1349. a560 2
  1350.     AlignPointer(inAlign, statePtr->inPtr);
  1351.     AlignPointer(outAlign, statePtr->outPtr);
  1352. d642 2
  1353. a643 2
  1354.     AlignPointer(inAlign, statePtr->inPtr);
  1355.     AlignPointer(outAlign, statePtr->outPtr);
  1356. d657 2
  1357. a658 2
  1358.     AlignPointer(inAlign, statePtr->inPtr);
  1359.     AlignPointer(outAlign, statePtr->outPtr);
  1360. d707 2
  1361. a708 2
  1362.     AlignPointer(statePtr->inInfoPtr->bAlign, inPtr);
  1363.     AlignPointer(statePtr->outInfoPtr->bAlign, outPtr);
  1364. d783 2
  1365. a784 2
  1366.     AlignPointer(statePtr->inInfoPtr->hAlign, inPtr);
  1367.     AlignPointer(statePtr->outInfoPtr->hAlign, outPtr);
  1368. d870 2
  1369. a871 2
  1370.     AlignPointer(statePtr->inInfoPtr->wAlign, inPtr);
  1371.     AlignPointer(statePtr->outInfoPtr->wAlign, outPtr);
  1372. d960 2
  1373. a961 2
  1374.     AlignPointer(statePtr->inInfoPtr->dAlign, inPtr);
  1375.     AlignPointer(statePtr->outInfoPtr->dAlign, outPtr);
  1376. @
  1377.  
  1378.  
  1379. 1.4
  1380. log
  1381. @changed some mistakes in converting doublewords using 4 bytes 
  1382. instead of 8
  1383. @
  1384. text
  1385. @d19 1
  1386. a19 1
  1387. static char rcsid[] = "$Header: /sprite/src/lib/c/etc/RCS/fmt.c,v 1.3 89/10/24 12:26:13 jhh Exp Locker: douglis $ SPRITE (Berkeley)";
  1388. d987 8
  1389. a994 8
  1390.         outPtr[0] = inPtr[3];
  1391.         outPtr[1] = inPtr[2];
  1392.         outPtr[2] = inPtr[1];
  1393.         outPtr[3] = inPtr[0];
  1394.         outPtr[4] = inPtr[7];
  1395.         outPtr[5] = inPtr[6];
  1396.         outPtr[6] = inPtr[5];
  1397.         outPtr[7] = inPtr[4];
  1398. @
  1399.  
  1400.  
  1401. 1.3
  1402. log
  1403. @made it compatible with old swapbuffer constants
  1404. @
  1405. text
  1406. @d19 1
  1407. a19 1
  1408. static char rcsid[] = "$Header: /sprite/src/lib/c/etc/RCS/fmt.c,v 1.2 89/06/19 14:16:11 jhh Exp Locker: jhh $ SPRITE (Berkeley)";
  1409. d955 1
  1410. a955 1
  1411.     if (inPtr + repCount * 4 > statePtr->inEndPtr) {
  1412. d965 1
  1413. a965 1
  1414.         outPtr + repCount * 4 > statePtr->outEndPtr) {
  1415. d982 2
  1416. a983 2
  1417.         inPtr += 4;
  1418.         outPtr += 4;
  1419. @
  1420.  
  1421.  
  1422. 1.2
  1423. log
  1424. @added sparc and mips format
  1425. @
  1426. text
  1427. @d19 1
  1428. a19 1
  1429. static char rcsid[] = "$Header: /sprite/src/lib/c/etc/RCS/fmt.c,v 1.1 89/06/05 12:34:44 jhh Exp Locker: jhh $ SPRITE (Berkeley)";
  1430. d93 6
  1431. d173 11
  1432. d244 11
  1433. @
  1434.  
  1435.  
  1436. 1.1
  1437. log
  1438. @Initial revision
  1439. @
  1440. text
  1441. @d19 1
  1442. a19 1
  1443. static char rcsid[] = "$Header: /sprite/lib/forms/RCS/proto.c,v 1.2 89/01/07 04:12:18 rab Exp $ SPRITE (Berkeley)";
  1444. d70 2
  1445. a71 2
  1446.     {1, 2, 4, 8, 4, 4, LITTLE_ENDIAN},       /* MIPS */
  1447.     {1, 2, 4, 8, 4, 4, BIG_ENDIAN},        /* SPARC */
  1448. @
  1449.